/**
 * Created on May 9, 2007
 */
package jvs.vfs;

import java.io.ByteArrayOutputStream;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Arrays;

import jvs.OS;
import jvs.vfs.sec.AccessControl;
import x.java.io.File;
import android.util.Log;

/**
 * @author qiangli
 * 
 */

public abstract class IFileBaseImpl implements IFile, Comparable<IFile> {
	protected static final boolean DEBUG = FileSystem.DEBUG;
	protected static final String LOG_TAG = "JVS LOG ";

	protected static final SimpleDateFormat df = new SimpleDateFormat(
			"yyyy-MM-dd HH:mm");

	protected static final FileSystem fs = FileSystem.getFileSystem();
	
	protected static final int LINK_EXT_LEN = File.LINK_EXT.length();

	protected static String name(String p) {
		if (p == null || p.equals("") || p.equals("/")) {
			return "";
		}
		if (p.endsWith("/")) {
			p = p.substring(0, p.length() - 1);
		}
		int idx = p.lastIndexOf("/");
		if (idx == -1) {
			return p;
		}
		return p.substring(idx + 1);
	}

	protected static String parent(String p) {
		if (p == null || p.equals("") || p.equals("/")) {
			return null;
		}
		if (p.endsWith("/")) {
			p = p.substring(0, p.length() - 1);
		}
		int idx = p.lastIndexOf("/");
		if (idx == -1) {
			return null;
		}
		if (idx == 0) {
			return "/";
		}
		return p.substring(0, idx);
	}

	protected static String path(URI uri) {
		String path = uri.getPath();
		if (path == null || path.equals("") || path.equals("/")) {
			path = "/";
		} else if (path.endsWith("/")) {
			path = path.substring(0, path.length() - 1);
		}
		return path;
	}

	protected URI uri;

	protected IFileBaseImpl() {
	}

	public IFileBaseImpl(URI uri) {
		this.uri = uri;
//		if (DEBUG) {
//			debug(this, uri);
//		}
	}

	public boolean canExecute() {
		return false;
	}

	public boolean canRead() {
		return false;
	}

	public boolean canWrite() {
		return false;
	}

	public int compareTo(IFile that) {
		return this.getName().compareTo(that.getName());
	}

	public boolean copy(URI uri) {
		java.io.InputStream in;
		try {
			in = getInputStream();
			OutputStream out = uri.toURL().openConnection().getOutputStream();
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	protected int count(InputStream in) throws IOException {
		int read = -1;
		byte[] b = new byte[File.BUFSIZE];
		int cnt = 0;
		while ((read = in.read(b)) != -1) {
			cnt += read;
		}
		return cnt;
	}

	abstract public boolean create();

//	protected void debug(Object o) {
//		if (o instanceof Throwable) {
//			Throwable t = (Throwable) o;
//			t.printStackTrace();
//			// Log.log(Log.TRACE,this,o);
//			return;
//		}
//		Log.log(Log.DEBUG, this, o);
//	}

	abstract public boolean delete();

	public void deleteOnExit() {
	}

	public boolean execute() {
		return false;
	}

	abstract public boolean exists();

	protected AccessControl getAccessControl() {
		return OS.getAccessControl();
	}

	public Object getAttribute(String name) {
		return null;
	}

	public String getContent() {
		try {
			InputStream in = getInputStream();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return out.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public String getContentEncoding() {
		return null;
	}

	public String getContentType() {
		return fs.guessType(getName());
	}

	public String getDisplayName() {
		String n = getName();
		if (n.endsWith(File.LINK_EXT)) {
			int len = n.length();
			n = n.substring(0, len - LINK_EXT_LEN);
		}
		return n;
	}

	public Object getIcon() {
		return null;
	}

	public abstract InputStream getInputStream();
	
	public long getLastModified() {
		return fs.getUptime();
	}
	
	public long getLength() {
		InputStream in = getInputStream();
		if (in == null) {
			return -1;
		}
		try {
			return count(in);
		} catch (IOException e) {
		} finally {
			try {
				in.close();
			} catch (IOException e) {
			}
		}
		return -1;
	}

	public String getName() {
		String p = uri.getPath();
		return name(p);
	}

	public abstract OutputStream getOutputStream();

	public OutputStream getOutputStream(boolean append) {
		if (append) {
			throw new RuntimeException("Not supported");
		}
		return getOutputStream();
	}

	protected String getParent() {
		String p = uri.getPath();
		return parent(p);
	}

	public String getPhoneticName() {
		return getDisplayName();
	}

	public String getSortKey() {
		return getDisplayName();
	}

	public abstract boolean isDirectory();

	public boolean isEmpty() {
		return (isDirectory() && list().length == 0);
	}

	public boolean isFile() {
		return !isDirectory();
	}

	public boolean isLocal() {
		return false;
	}

	public boolean isNative() {
		return false;
	}

	public abstract String[] list();

	public String[] list(int off, int max) {
		String[] l = list();
		if (l == null) {
			return null;
		}
		int len = l.length;
		if (off >= len) {
			return new String[0];
		}
		Arrays.sort(l);
		len = Math.min(len, off + max);
		String[] rl = new String[len - off];
		for (int i = off; i < len; i++) {
			rl[i - off] = l[i];
		}
		return rl;
	}

//	public Cursor listc(FileFilter filter, Comparator<java.io.File> c) {
//		return null;
//	}

	public IFile[] listFiles() {
		return null;
	}

	public IFile[] listFiles(FileFilter filter) {
		return null;
	}

	public IFile[] listFiles(FilenameFilter filter) {
		return null;
	}

	public IFile[] listFiles(int off, int max) {
		IFile[] l = listFiles();
		if (l == null) {
			return null;
		}
		int len = l.length;
		if (off >= len) {
			return new IFile[0];
		}
		Arrays.sort(l);//
		len = Math.min(len, off + max);
		IFile[] rl = new IFile[len - off];
		for (int i = off; i < len; i++) {
			rl[i - off] = l[i];
		}
		return rl;
	}

//	public int listi(int pagesize, Collector<Index> indice) {
//		return -1;
//	}

	public abstract boolean mkdir();

	public abstract boolean move(URI uri);

	public void refresh() {
	}

	public boolean setAttribute(String name, Object value) {
		return false;
	}

	public boolean setContent(String s) {
		try {
			OutputStream out = getOutputStream();
			Writer w = new OutputStreamWriter(out);
			w.write(s);
			w.close();
			out.close();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean setContentEncoding(String encoding) {
		return false;
	}

	public boolean setContentType(String mimeType) {
		return false;
	}

	public boolean setInputStream(InputStream in) {
		try {
			OutputStream out = getOutputStream();
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	public boolean setLastModified(long time) {
		return false;
	}

	public boolean setLength(long len) {
		return false;
	}

	public boolean setOutputStream(OutputStream out) {
		try {
			java.io.InputStream in = getInputStream();
			byte buf[] = new byte[File.BUFSIZE];
			int len;
			while ((len = in.read(buf, 0, File.BUFSIZE)) != -1) {
				out.write(buf, 0, len);
			}
			in.close();
			out.close();
			return true;
		} catch (Exception e) {
		}
		return false;
	}

	public URI toRealURI() {
		return uri;
	}

	@Override
	public String toString() {
		return uri.toString();
	}
	
	public Object getImage() {
		return null;
	}
	
	protected void debug(Object tag, Object msg) {
		Log.d(LOG_TAG, tag+ ": "+msg);
	}
}
